package com.own.component.log.operation.util;

import com.own.component.client.base.RequestClientManager;
import com.own.component.common.login.user.BaseLoginUser;
import com.own.component.common.util.IpUtil;
import com.own.component.common.util.RequestUtil;
import com.own.component.common.util.executor.ExecutorUtil;
import com.own.component.log.operation.aop.LogOperationAop;
import com.own.component.log.operation.core.ExtraLogOperationSpringHook;
import com.own.component.log.operation.core.PersistenceLogOperationSpringHook;
import com.own.component.log.operation.entity.LogOperationEntity;
import com.own.component.log.operation.property.LogOperationProperty;
import com.own.constant.ConstantCommon;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.HashMap;

/**
 * LogOperationErrorInterceptorUtil
 *
 * @author chenxueli
 * @date 2023-08-26 10:31:00
 */
@Slf4j
@Component
public class LogOperationErrorInterceptorUtil {

    @Resource
    private RequestClientManager requestClientManager;

    @Resource
    private LogOperationProperty logOperationProperty;

    @Resource
    private ExtraLogOperationSpringHook extraLogOperationSpringHook;
    @Resource
    private PersistenceLogOperationSpringHook persistenceLogOperationSpringHook;

    @Resource
    private ExecutorUtil executorUtil;

    /**
     * 记录拦截器的错误日志信息
     *
     * @param loginUser 登录方法
     * @param method    方法
     * @param request   请求
     * @param message   错误信息
     */
    public void run(
            BaseLoginUser loginUser,
            Method method,
            HttpServletRequest request,
            String errorCode,
            String message
    ) {
        var logOperationAop = method.getAnnotation(LogOperationAop.class);
        if (logOperationAop != null) {
            // 获取日志信息（不需要新的线程，防止数据丢失）
            var moduleName = LogOperationUtil.getModuleName(method.getDeclaringClass(), logOperationAop);
            var methodName = method.getDeclaringClass().getName() + "." + method.getName();
            var entity = new LogOperationEntity();
            // 执行其他的信息
            {
                var extra = new HashMap<String, Object>();
                var list = extraLogOperationSpringHook.get(logOperationAop.type());
                list.forEach(item -> extra.put(item.name(), item.collect()));
                entity.setExtra(extra);
            }
            entity.setLevel(logOperationAop.level());
            entity.setIp(IpUtil.getIpAddress(request));
            entity.setClient(requestClientManager.client(request));
            entity.setLoginUser(loginUser);
            entity.setModuleName(moduleName);
            entity.setOperationName(LogOperationUtil.getOperationName(method, logOperationAop));
            entity.setMethodName(methodName);
            entity.setRequest(new LogOperationEntity.ExtraRequestParam(LocalDateTime.now(), RequestUtil.body(request)));
            // 获取返回值
            entity.setMessage(message);
            entity.setStatus(2);
            entity.setCode(errorCode);
            entity.setResponse(new LogOperationEntity.ExtraResponseParam(LocalDateTime.now(), null));
            entity.setRequestUrl(request.getRequestURI());
            entity.setRequestMethod(request.getMethod());
            entity.setTraceId(MDC.get(ConstantCommon.TRACE_ID));
            entity.setHeaders(RequestUtil.headerForDecode(request));
            entity.setService(logOperationProperty.getServiceName());
            // 记录日志信息
            executorUtil.execute(() -> persistenceLogOperationSpringHook.run(entity));
        }
    }

}
